1. Assignment 1: Simple Counter

The goal of this first assignment is to get familiar with writing a testbench for a very simple module, and start the simulation.

We will write a very simple counter first, then enhance it with a few features, and improve the testbench along the way.

The goal of this assignment is to get used to:

  • Writing code
  • Quick check the syntax with the simulator
  • Prepare a test bench
  • Improve the design incrementally and quickly rerun the tools

Tip

The tutorials about the tools are located in the Tools and Languages sections, go back to them whenever you forgot how a tool works.

Tip

The Verilog Syntax and features is explained in the lecture part Verilog Hardware Description Language , we will refer to it when necessary.

Tip

The assignments descriptions don’t show much code, but refer to the tutorials and lecture where you can find examples.

1.1. Cadence Tools

First you should read about the Cadence Tools and the Tool Irun, to learn how to start the tool.

1.2. Organising your work Folder

To work on the assignments, you should create a folder for DDS, called for example “dds17”, and create a sub folder per assignment.

If you have never used a Linux command Line, you can look at the Linux tutorial.

For this assignment, the folder structure could look like:

  • dds17/
    • assignment1/

1.3. Assignments Plan

The assigment plan for the Lab work is not fixed.

If you are slower or faster than the time table it is not really important, you should just focus on learning how to design the circuit, simulate it and implement it.

1.4. First Version

1.4.1. Specification

To start off, we will create an 8 bit Counter that simply increments its value upon a clock positive edge.

As we have seen in the lecture, a System is usually represented by a drawing of a Box with input and outputs drawn as arrows:

../../_images/counter1.png

This picture means, we will declare a Module called “counter” with:

  • One input called “clk”
  • One output called “value”, with a size of 8 bits
  • The value must be a register , because the value is incremented and updated at a clock cycle edge
  • The clock is the input “clk”

Hint

Create a file called “counter.v” , and create a Module with Input/Outputs for the counter

Hint

Look at the Lecture to see how to code in Verilog, don’t hesitate to copy-paste and rename

Hint

Don’t implement to counting part right now, we will first check if the code is correct.

1.4.2. Simulation: Syntax Check

So far we should have written a very few lines of code, but we want to check right away that no syntax error are present, like:

  • Missing “,” or “;”
  • Unbalanced parenthesis
  • Extra “,” at the end of a list etc…

To do that, we will start cadence-irun on the file “counter.v”.

The command should look like:

~/dds17/assignment1 $ irun counter.v

Or if you are using a command file:

~/dds17/assignment1 $ irun -f counter.f

Hint

Look at the cadence-irun reference to learn about irun.

Hint

If your design is error free, you can continue

1.4.3. Simulation: Create a testbench

Tip

Look at the Lecture Simulation Testbench to learn how to code the elements of this section

We have briefly introduced in the lecture that a Simulation is a piece of software which drives the inputs of the tested design.

To begin with the testbench, you need to write down which inputs are to be driven and how.

Question

Which input does the test bench need to drive to simulate our simple counter?

To create the testbench, open a new file which you can call “counter_tb.v”, and prepare a Verilog Module called “counter_tb”.

Hint

the suffix “_tb” in the file name and module name is a widely used way to name test bench modules and files to ease readiness.

Once you have created the testbench module, you need to add:

  • A Module Instance of the counter.
  • A clock register which the testbench software will drive.
  • A clock generator.

Start the simulation using irun passing both files as input, and with the Graphical Environment Simvision:

~/dds17/assignment1 $ irun -gui -access +rw counter.v counter_tb.v

Question

Can you see the Testbench and Counter hierarchy in the design browser

Question

Start the simulation in a Waveform window, can you see the clock running?

1.4.4. Implementation: Counting

So far we have passed the first step to implement the design:

  • Create the Module, it’s input and outputs, and the Testbench Hierarchy
  • Define and generate a clock to drive the design

This order of design should be the same as we have have presentend during the lecture.

Now we would like the counter to actually count, so we will have to implement the circuit. To do so, we will need:

  • A Pipeline Stage reacting to the positive edge of the clock
  • An assignment to update the counter value output.

Go back to the “counter.v” file, and add the code.

Tip

Pipeline stages are described in the lecture

Todo

Reinvoke the simulator (see irun tutorial) and run the simulation, add the value output of the counter to the waveform.

Question

What do you see in the waveform? can you see a value counting?

1.4.5. Implementation: Reset

If everything works as expected, you should not see the value increment, but instead a constant red X.

The X value means “undefined”, as shortly described in the lecture.

The simulator will never update an undefined value, because it does not know how to start.

Theoretically, in real life, the counter would have some value and count from there. However, most signals in a design need a defined state.

Todo

Add a Reset Block to the pipeline stage, and an output. Set the counter value initially to 0.

../../_images/counter-reset.png

Todo

Add a Reset sequence to the simulation to the test bench.

Todo

Reinvoke the simulator and run the simulation…can you see the value update now?

1.5. Simulation Improvement and Next feature

We should now have covered the minimal basics to quick off a digital design:

  • Create a Module
  • Create a testbench
  • Add a clock generator and a reset sequence
  • Get used to restarting the simulation

From here on, we will then add more features to the counter.

For each of the described features, you should:

  • Implement it in the counter Module
  • Drive the signal from the test bench to test it
  • Make the testbench fail if the counter does not behave as expected

This assignment will be detailed as before, and the next features will just be described and left for you to implement.

1.5.1. Testbench preparation for unit testing

Now that we are adding more features, we could improve the test bench to make it “clever” and actively test the features.

To do so, it is easy to add display text for the command line output, and even error reporting.

For example, the actual test bench you have written so far just resets the counter, runs for a while then reaches $finish. You could improve the test bench to display some text, like you would in a normal C software.

For example:

initial
begin

   ...

   ...
   $display("Finished...")
   $finish();

end

Or in case of error:

initial
begin

   ...

   // test the output of the DUT
   if (tested_output == 0) begin

      // Will stop simulation
      $fatal("tested_output  should be 1 here...");

   end

   ...

   $display("Finished...")
   $finish();

end

Warning

$fatal is part of SystemVerilog, you should add the -sv to the command line when calling irun

Tip

Look at the System Verilog reference document , Section 23 (System Tasks)

1.5.2. Enable

An enable signal is a control signal, which typically stops the activity.

You should:

  • Add a new input to the counter, which stops the counter when 0, and resumes when 1
  • Improve the testbench to test the sequence
../../_images/counter-enable.png

Tip

Consult the lecture Simulation Synchronisation for simple examples on how to sycnhronise the testbench with the design.

Question

How/When did you change the enable signal in the testbench? Did it work correctly?

1.5.3. Reinit

A reinit signal is very similar to a reset and provides the same functionality.

However, resets are meant to bring a system to an initial state, and reinit signals to bring a certain module to a start state.

You should:

  • Add a new input to reinitialise the counter
  • Improve the test bench to test this signal
../../_images/counter-reinit.png

Tip

The Reinit should be similar to reset right now.

Tip

Use the reinit signal to reset the counter between features tests

1.5.4. Overflow

A classical counter device will offer an overflow output. Overflows are used for example in a processor system to be woken by interrupt after a certain time and perform an operation.

Typically, interrupt signals have to be cleared manually by the interrupt handler to avoid being triggered if the handler is slower than the interrupt generation rate.

You should:

  • Add an overflow output, which toggles to 1 when the counter’s value comes back to 0
  • Add a matching clear_overflow input, which resets the overflow value back to 0
  • Add an overflow_error output
    • If the counter overflows when overflow is still 1, overflow_error is set to 1, the counter stops
    • If the counter enters overflow error, only asserting reinit can reset it
../../_images/counter-overflow.png

Todo

Implement the features and test them in the test bench

Todo

Write down the use cases of this overflow to make sure you don’t miss a test

Question

How many test cases do you need?

Question

Did you forget to test the error case?

1.6. Making Configurable

Our counter now has a few features, however, it is still 8 bit wide.

You may have noticed by now, that the counter could be more or less than 8bits and require no changes in the implementation of the control features.

Todo

Look at the lecture part about Paremeterizing and make the width of the counter configurable with a parameter

Tip

Constants assignments require variable size assignment, look in the lecture at: Constant to Variable Size Assignment

Todo

Update the features dependending on the counter width, like the overflow.

Todo

Update the testbench and Make sure the features still work. if the testbench was written correctly, it should fail on error.

1.7. Shift Register output

To finish this first round of feature implementation, we will add a second counting output, based on a shift register. To make the design more interesting, we will also make this second output run on a different clock.

You should then:

  • Add a “clk_sr” to drive the shift register counter
  • Add a “reset_sr” to reset the shift register counter
  • An “enable_sr” input to enable/disable the shift register counter
  • Add an output “value_sr” for the shift register output
../../_images/counter-sr.png

Todo

Prepare the input/outputs then the pipeline stage for the shift register output.

The Shift Register Counter basic construction will be detailed during the lecture.

For now we can create a simple Johnson or Ring Counter , which is simply:

  • A Shift Register
  • The input of the first bit is the output of the last bit inverted
../../_images/sr-def.png

Todo

Find How to assign the value_sr output to itself to implement the Shift Register Behaviour

Tip

Look at the lecture part about value assignment to find a way to define the shift register

Todo

Update the testbench by adding appropriate clock, reset and enable for the shift register output

Tip

Don’t hesitate to make the clocks run at different speeds to better see the difference in the waveform

1.8. Short Conclusion

During this first assigment, we have learned how to:

  • Create a module for a simple circuit
  • Setup an associated testbench
  • Defined basic reset and reinit signals
  • Add some features and test them using the test bench
  • Create a shift register
  • Run a parts of the logic under separated clocks.

In the next assignment we will look at the Synthesis Process to create a real circuit representation of the counter.